/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "DataSourceXM.h"
#include <resource/Manager.h>
#include "PCMConvert.h"
#include "xm/XMPlayer.h"
#include <boost/scoped_ptr.hpp>

namespace liba
{
namespace noise
{

DataSourceXM::DataSourceXM( const filesystem::String & file_name )
{
	boost::scoped_ptr<resource::Resource> res(resource::Manager::create_resource( file_name + ".xm" ));
	xm_player = new XMPlayer( res.get(), Format( 22050, 2, 16 ), true );
}

DataSourceXM::~DataSourceXM()
{
	delete xm_player; xm_player = 0;
}

bool DataSourceXM::is_valid()const
{
	return xm_player->is_valid();
}

int DataSourceXM::get_frequency()
{
	return xm_player->get_format().get_frequency();
}

bool DataSourceXM::has_native(Type channel)
{
	return channel == DataSource::STEREO_LEFT || channel == DataSource::STEREO_RIGHT;
}

int DataSourceXM::decode(int samples)
{
	int required_size = samples * xm_player->get_format().get_sample_size();
	decoded_data.resize( 0 );
	decoded_data.resize( required_size, 0 );

	samples_decoded = xm_player->read( &(decoded_data.front()), samples );
	if( samples_decoded == 0 )
		xm_player->reset();

	return samples_decoded;
}

void DataSourceXM::get_data(Type channel, void * dst, int dst_stride, int dst_bits)
{
	int chan = 0;

	switch( channel )
	{
	case DataSource::MONO:
	case DataSource::STEREO_LEFT:
	case DataSource::SURROUND_FRONTLEFT:
	case DataSource::SURROUND_REARLEFT:
	case DataSource::SURROUND_SUBWOOFER:
	case DataSource::SURROUND_CENTER:
		chan = 0;
		break;
	case DataSource::STEREO_RIGHT:
	case DataSource::SURROUND_FRONTRIGHT:
	case DataSource::SURROUND_REARRIGHT:
		chan = 1;
		break;
	}
	int src_bits = xm_player->get_format().get_bit_rate();
	int src_bytes = (src_bits + 7) / 8;
	int src_stride = xm_player->get_format().get_sample_size();
	return pcm_bit_convert( chan * src_bytes + &(decoded_data.front()), src_stride, src_bits, src_bytes,
		dst, dst_stride, dst_bits, (dst_bits + 7) / 8, samples_decoded );
	// info.nChannels == 6
	/*switch( channel )
	{
	case DataSource::MONO:
	case DataSource::STEREO_LEFT:
	case DataSource::STEREO_RIGHT:
	case DataSource::SURROUND_FRONTLEFT:
	case DataSource::SURROUND_FRONTRIGHT:
	case DataSource::SURROUND_REARLEFT:
	case DataSource::SURROUND_REARRIGHT:
	case DataSource::SURROUND_SUBWOOFER:
	case DataSource::SURROUND_CENTER:
	}*/
}

} // namespace noise
} // namesapce liba

